package com.my.study.advice;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.my.study.annotation.Encrypt;
import com.my.study.config.EncryptProperties;
import com.my.study.entity.vo.ResponseVO;
import com.my.study.enums.BusinessExceptionEnum;
import com.my.study.exception.BusinessException;
import com.my.study.util.AESUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

@EnableConfigurationProperties(EncryptProperties.class)
@ControllerAdvice
@Slf4j
public class EncryptResponse implements ResponseBodyAdvice<ResponseVO> {

    private ObjectMapper om = new ObjectMapper();

    @Autowired
    EncryptProperties encryptProperties;

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return returnType.hasMethodAnnotation(Encrypt.class);
    }


    @Override
    public ResponseVO beforeBodyWrite(ResponseVO body, MethodParameter returnType, MediaType selectedContentType,
                                      Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        byte[] keyBytes = encryptProperties.getKey().getBytes();
        try {
            if (body.getData() != null) {
                body.setData(AESUtils.encrypt(om.writeValueAsBytes(body.getData()), keyBytes));
            }
        } catch (Exception e) {
            log.error("beforeBodyWrite error:" + e);
            throw BusinessException.fail(BusinessExceptionEnum.FAIL.code, BusinessExceptionEnum.FAIL.msg);
        }
        return body;
    }
}

